﻿// resource_monitor.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <Windows.h>
#include "io.h"
#include <iostream>
#include <iomanip>
#include "string.h"
#include <stdlib.h>
#include <openssl/ossl_typ.h>
#include <openssl/hmac.h>
#include <math.h>
#include "string.h"
#include <Winsock2.h>
#include <string>

using namespace std;
#pragma comment(lib, ".\\libssl.lib")
#pragma comment(lib, ".\\libcrypto.lib")
#pragma comment(lib,"ws2_32.lib")

char* monitor_ip = "192.168.1.109";

__int64 CompareFileTime(FILETIME time1, FILETIME time2)
{
    __int64 a = (__int64)(time1.dwHighDateTime) << 32 | (__int64)(time1.dwLowDateTime);
    __int64 b = (__int64)(time2.dwHighDateTime) << 32 | (__int64)(time2.dwLowDateTime);

    return (b - a);
}

/*CPU占用读取变量*/
BOOL res;
int CPU_usage;
int Mem_usage;

FILETIME preidleTime;
FILETIME prekernelTime;
FILETIME preuserTime;

FILETIME idleTime;
FILETIME kernelTime;
FILETIME userTime;

int get_CPU_usage_init(void)
{
    res = GetSystemTimes(&idleTime, &kernelTime, &userTime);

    preidleTime = idleTime;
    prekernelTime = kernelTime;
    preuserTime = userTime;

    return 0;
}
int get_CPU_usage(void)
{
    res = GetSystemTimes(&idleTime, &kernelTime, &userTime);

    __int64 idle = CompareFileTime(preidleTime, idleTime);
    __int64 kernel = CompareFileTime(prekernelTime, kernelTime);
    __int64 user = CompareFileTime(preuserTime, userTime);
    int cpu = (kernel + user - idle) * 100 / (kernel + user);
    //cout << kernel << "     " << user << "     " << idle << endl;
    preidleTime = idleTime;
    prekernelTime = kernelTime;
    preuserTime = userTime;

    return cpu;
}

/*内存使用率*/
//windows 内存 使用率  
DWORD getWin_MemUsage(void)
{
	MEMORYSTATUSEX ms;
	ms.dwLength = sizeof(ms);
    GlobalMemoryStatusEx(&ms);
	//cout << left << setw(17) << "内存占用率：" << setw(3) << ms.dwMemoryLoad << "%" << endl;
    return ms.dwMemoryLoad;
}

void time_sleep(int ms) {
	Sleep(ms);
}

/*post请求*/
#define IPSTR "192.168.1.109" //服务器IP地址;
#define PORT 80 //服务器端口;
#define BUFSIZE 1024

class httpClient {
	std::string host;
	std::string path;
	std::string post_content;
public:
	std::string httpSend(std::string httpHeader);
	std::string httpGet(std::string host, std::string path);
	std::string httpPost(std::string host, std::string path, std::string post_content);
};
std::string httpClient::httpSend(std::string httpHeader) {
	//POST请求方式
	std::string ret = ""; // 返回Http Response
	// 开始进行socket初始化
	WSADATA wData;
	::WSAStartup(MAKEWORD(2, 2), &wData);
	SOCKET clientSocket = socket(AF_INET, 1, 0);
	struct sockaddr_in ServerAddr = { 0 };
	ServerAddr.sin_addr.s_addr = inet_addr(IPSTR);
	ServerAddr.sin_port = htons(PORT);
	ServerAddr.sin_family = AF_INET;
	int errNo = connect(clientSocket, (sockaddr*)&ServerAddr, sizeof(ServerAddr));
	if (errNo == 0) {
		errNo = send(clientSocket, httpHeader.c_str(), httpHeader.length(), 0);//发送头文件 
		if (errNo > 0) {
			std::cout << "发送成功" << std::endl;
		}
		else {
			std::cout << "errNo:" << errNo << std::endl;
			return ret;
		}
		// 接收
		char bufRecv[3069] = { 0 };
		errNo = recv(clientSocket, bufRecv, 3069, 0);
		if (errNo > 0) {
			ret = bufRecv;// 如果接收成功，则返回接收的数据内容
			char* p;
			char* delims = { "\n" };
			p = strtok(bufRecv, "\n");
			int i = 0;
			while (p != NULL) {
				if (i == 13) {
					//					printf("word: %s\n",p); //对获取的数据进行分割，获取每一行的数据 
					ret = p;
				}
				i++;
				p = strtok(NULL, delims);
			}
			return ret;
		}
		else {
			std::cout << "errNo:" << errNo << std::endl;
			return ret;
		}
		return "0";
	}
	else {
		errNo = WSAGetLastError();
		std::cout << "errNo:" << errNo << std::endl;
	}
	// socket环境清理
	::WSACleanup();
	return ret;
}
/** Get 请求 */
std::string httpClient::httpGet(std::string host, std::string path) {
	std::string httpHeader;
	httpHeader =
		"GET " + path + " HTTP/1.1\r\n"
		"Host: " + host + "\r\n"
		"User-Agent: IE or Chrome\r\n"
		"Accept-Type: */*\r\n"
		"Connection: Close\r\n\r\n";
	return httpSend(httpHeader);
}
/** Post 请求 */
std::string httpClient::httpPost(std::string host, std::string path, std::string post_content) {
	std::string httpHeader;
	char lenChar[16]; //这个长度根据需要吧
	sprintf(lenChar, "%d", (int)post_content.length());
	std::string len(lenChar);
	httpHeader =
		"POST " + path + " HTTP/1.1\r\n"
		"Accept-Encoding: gzip, deflate"
		"Host: " + host + "\r\n"
		"Connection: keep-alive\r\n"
		"Content-Type: application/x-www-form-urlencoded\r\n"
		"Content-Length: " + len + "\r\n\r\n"
		+ post_content;
	return httpSend(httpHeader);
}

int main()
{
    HANDLE hEvent;

    get_CPU_usage_init();

	httpClient* http = new httpClient();
	time_sleep(3000);

    hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); // 初始值为 nonsignaled ，并且每次触发后自动设置为nonsignaled
	if (!hEvent)return -1;
	

    while (1)
    {
		WaitForSingleObject(hEvent, 500); //等待500毫秒
        CPU_usage = get_CPU_usage();
		Mem_usage = getWin_MemUsage();
        cout << "CPU Usage: " << CPU_usage << "%" << endl;
        cout << "Mem Usage: " << Mem_usage << "%" << endl;

		/*post*/
		std::string message = "cpu_usage=" + to_string(CPU_usage) + "&mem_usage=" + to_string(Mem_usage);
		std::cout << "POST:" << http->httpPost("192.168.1.109", "/device/", message) << std::endl;
    }

    return 0;
}

// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门使用技巧: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件，或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来，若要再次打开此项目，请转到“文件”>“打开”>“项目”并选择 .sln 文件
